package graphic.tests;
import game.Coordinate;
import game.Entity2D;
import game.examples.newEntityCreation.ExampleTheadBased2DEntity;
import graphic.render.Render2D;
import graphic.render.StandardRender;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import javax.swing.JFrame;

import utils.TestMouseListener;

/**
 * 
 * @author Jan
 *
 */
public class RenderTest03 extends Canvas implements Runnable{


	private static final long serialVersionUID = -2937001437943245458L;
	
	public static final int WIDTH = 1280;
	public static final int HEIGHT = 720;
	
	private boolean isRunning = false;
	private Thread thread;
	
	//Limitatore per ridurre il carico "inutile" della GPU.
	private final long renderLimiter = 2;
	
	private BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
	private int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
	
	private Render2D renderScreen;
	private Entity2D testMob = new ExampleTheadBased2DEntity(1, new Coordinate(250, 250, 0), 0);
	
	public RenderTest03() {
		super();
		Dimension dimension = new Dimension(WIDTH, HEIGHT);
		setPreferredSize(dimension);
		setFocusable(true);
		
		TestMouseListener mouse = new TestMouseListener(testMob);
		addMouseMotionListener(mouse);
	}
	
	/**
	 * Metodo per l'avvio del Thread grafico.
	 */
	public synchronized void start(){
		isRunning = true;
		thread = new Thread(this, "Test Thread");
		thread.start();
	}
	
	/**
	 * Metodo per lo stop del Thread grafico.
	 */
	public synchronized void stop(){
		isRunning = false;
		try {
			thread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void init(){
		renderScreen = new StandardRender();
		renderScreen.setRenderAreaPixels(pixels);
		renderScreen.setRenderAreaWidth(WIDTH);
		renderScreen.setRenderAreaHeight(HEIGHT);
	}
	
	@Override
	public void run() {

		long lastTime = System.nanoTime();		
		double nsPerTick = 1000000000D/60; 		// FPS
		
		int ticks = 0;
		int frames = 0;	
		
		long lastTimer = System.currentTimeMillis();
		
		double delta = 0;						
		
		init();
		
		while(isRunning){
			long now = System.nanoTime();
			delta += ( now - lastTime )/nsPerTick;
			lastTime = now;
			
			//boolean needRender = false;		//Attiva il blocco.
			boolean needRender = true;
			
			while( delta >= 1){					
				ticks++;
				tick();
				delta -= 1;
				needRender = true;
			}
			
			try {
				Thread.sleep(renderLimiter);				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			if(needRender){
				frames++;
				render();
			}
			
			
			if( (System.currentTimeMillis() - lastTimer) >= 1000 ){
				lastTimer += 1000;
				System.out.println( frames+","+ticks );
				frames = 0;
				ticks = 0;
			}
		}
	}
	
	/**
	 * Metodo per l'aggiornamento dei pixel da renderizzare.
	 */
	public void tick(){
		renderScreen.cleanRenderArea();
		//Test del disegno con un solo canale RGB attivo.
//		renderScreen.monoChromaticCentredRender(RenderScreen.ONLY_RED, testMob );
		renderScreen.monoChromaticCentredRender(Render2D.ONLY_GREEN, testMob );
//		renderScreen.monoChromaticCentredRender(RenderScreen.ONLY_BlUE, testMob );
	}
	
	/**
	 * Metodo per la renderizzazione effettiva dei frame, usando i pixel aggiornati con tick.
	 */
	public void render(){
		BufferStrategy buffer = getBufferStrategy();
		if(buffer == null){
			createBufferStrategy(3);
			return;
		}
		
		
		Graphics2D g = (Graphics2D)buffer.getDrawGraphics();
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(img, 0, 0, getWidth(), getHeight(),null);
		
		g.dispose();
		buffer.show();
	}
	

	public static void main(String[] args) {
		JFrame frame = new JFrame();
		RenderTest03 game = new RenderTest03();
		frame.add(game);
		frame.pack();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		frame.setResizable(false);
		frame.setLocationRelativeTo(null);
		game.start();
	}
}
